package org.huaiyan.oauth.uaa.config;

import org.huaiyan.oauth.uaa.config.beans.JwtTokenEnhancer;
import org.huaiyan.oauth.uaa.services.impl.TabAdminUserServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;


/**
 * Created with IntelliJ IDEA 2020.3
 *
 * @EnableAuthorizationServer 表示当前是属于一个授权服务
 * @author: huaiyan
 * Date: 2021-10-19 11:07
 * Description: 文件描述信息
 */
@Configuration
@EnableAuthorizationServer
public class MyAuthenticationServiceConfig extends AuthorizationServerConfigurerAdapter {

    public static final Logger logger = LoggerFactory.getLogger(MyAuthenticationServiceConfig.class);

    @Autowired
    private TabAdminUserServiceImpl tabAdminUserService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    @Qualifier("redisTokenStore")
    private TokenStore redisTokenStore;

    @Autowired
    @Qualifier("jwtTokenStore")
    private TokenStore jwtTokenStore;

    @Autowired
    private JwtAccessTokenConverter jwtAccessTokenConverter;

    @Autowired
    private JwtTokenEnhancer jwtTokenEnhancer;


    /**
     * 客户端管理
     *
     * @param clients 客户端
     * @return void
     * @date 2021/10/19 14:33
     * @author huaiyan
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {

        /**
         * 实际应用中肯定是放在DB中的,现在为了测试方便就放在内存中
         */
        // password 密码模式(将用户名,密码传过去,直接获取token)
        // refresh_token 刷新access_token
        // client_credentials 客户端模式(无用户,用户向客户端注册,然后客户端以自己的名义向’服务端’获取资源)
        // 这种一般情况下是DB 的,不是写死的
        clients.inMemory()
                // appid 哪台服务端可以请求进来
                .withClient("demo-client")
                // appsecret
                .secret(passwordEncoder.encode("demo-secret"))
                // 回调地址
                .redirectUris("http://www.baidu.com")
                /**
                 * 设置令牌有效期,默认是两周
                 */
                .accessTokenValiditySeconds(60)
                /**
                 * 控制刷新令牌的有效期时间
                 */
                .refreshTokenValiditySeconds(120)
                // 授权范围 -- 作用域
                .scopes("all")
                /**
                 * 表示当前客户端支持的授权方式
                 * 授权码模式（authorization_code） 授权码模式(最复杂的,但是是最安全的,也是用的最多的)
                 * 简化模式（implicit） 简化(隐藏)模式
                 * 密码模式（password） 密码模式
                 * 客户端模式（client_credentials）  客户端(凭证)模式
                 * 扩展模式（Extension）
                 * 令牌刷新 (refresh_token)
                 */
                .authorizedGrantTypes("authorization_code", "password","implicit","client_credentials","refresh_token");
                // 是否开启自动授权
//                .autoApprove(true);
    }


    /**
     * 配置密码模式的开启
     *
     * @param endpoints 节点
     * @return void
     * @date 2021/10/19 14:42
     * @author huaiyan
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        TokenEnhancerChain enhancer = new TokenEnhancerChain();
        /**
         * 自定义扩展JWT信息
         */
        List<TokenEnhancer> list = new ArrayList<>();
        list.add(jwtTokenEnhancer);
        list.add(jwtAccessTokenConverter);
        enhancer.setTokenEnhancers(list);
        /**
         * 开启密码模式 authenticationManager
         */
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(tabAdminUserService)
                /**
                 * 不开启这个的话,我们的令牌都是基于内存存储的,服务重置就会丢失,现防止丢失
                 * 与redis进行结合
                 */
//                .tokenStore(redisTokenStore);
                /**
                 * 使用无关系令牌JWT-代替redis
                 */
                .tokenStore(jwtTokenStore)
                /**
                 * 使用JWT需要依赖这个
                 */
                .accessTokenConverter(jwtAccessTokenConverter)
                /**
                 * 扩展JWT信息生效
                 */
                .tokenEnhancer(enhancer);
    }
}
